/**
 *  (c)
 * <p>
 *
 * <p>
 *
 */

package com.nn.smart.bus.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.nn.smart.bus.commons.mybatis.enums.DelFlagEnum;
import com.nn.smart.bus.commons.mybatis.service.impl.BaseServiceImpl;
import com.nn.smart.bus.commons.tools.constant.Constant;
import com.nn.smart.bus.commons.tools.constant.FieldConstant;
import com.nn.smart.bus.commons.tools.constant.NumConstant;
import com.nn.smart.bus.commons.tools.enums.SuperAdminEnum;
import com.nn.smart.bus.commons.tools.exception.NNException;
import com.nn.smart.bus.commons.tools.page.PageData;
import com.nn.smart.bus.commons.tools.security.password.PasswordUtils;
import com.nn.smart.bus.commons.tools.security.user.SecurityUser;
import com.nn.smart.bus.commons.tools.security.user.UserDetail;
import com.nn.smart.bus.commons.tools.utils.ConvertUtils;
import com.nn.smart.bus.commons.tools.utils.Result;
import com.nn.smart.bus.dao.SysUserDao;
import com.nn.smart.bus.dto.SysUserDTO;
import com.nn.smart.bus.dto.SysUserOpenIdFormDTO;
import com.nn.smart.bus.dto.epdc.GridForLeaderRegisterDTO;
import com.nn.smart.bus.dto.epdc.GridLeaderRegisterDTO;
import com.nn.smart.bus.dto.epdc.form.EpdcScripUserInfoFormDTO;
import com.nn.smart.bus.entity.SysUserEntity;
import com.nn.smart.bus.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户管理
 *
 * @author nanning
 * @since 1.0.0
 */
@Service
public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
    @Autowired
    private SysRoleUserService sysRoleUserService;
    @Autowired
    private SysDeptService sysDeptService;

    @Override
    public PageData<SysUserDTO> page(Map<String, Object> params) {
        //转换成like
        paramsToLike(params, "username");
        paramsToLike(params, "realname");
        paramsToLike(params, "mobile");
        paramsToLike(params, "email");
        //分页
        IPage<SysUserEntity> page = getPage(params, Constant.CREATE_DATE, false);

        //普通管理员，只能查询所属部门及子部门的数据
        UserDetail user = SecurityUser.getUser();
        if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            params.put("deptIdList", sysDeptService.getSubDeptIdList(user.getDeptId()));
        }

        //查询
        List<SysUserEntity> list = baseDao.getList(params);

        return getPageData(list, page.getTotal(), SysUserDTO.class);
    }

    @Override
    public List<SysUserDTO> list(Map<String, Object> params) {
        //普通管理员，只能查询所属部门及子部门的数据
        UserDetail user = SecurityUser.getUser();
        if (user.getSuperAdmin() == SuperAdminEnum.NO.value()) {
            params.put("deptIdList", sysDeptService.getSubDeptIdList(user.getDeptId()));
        }

        List<SysUserEntity> entityList = baseDao.getList(params);

        return ConvertUtils.sourceToTarget(entityList, SysUserDTO.class);
    }

    @Override
    public SysUserDTO get(Long id) {
        SysUserEntity entity = baseDao.getById(id);
        SysUserDTO dto = ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
        return dto;
    }

    @Override
    public SysUserDTO getByUsername(String username) {
        SysUserEntity entity = baseDao.getByUsername(username);
        return ConvertUtils.sourceToTarget(entity, SysUserDTO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SysUserDTO dto) {

        this.verifyUsernameAndMobile(dto);

        SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);

        //密码加密
        String password = PasswordUtils.encode(entity.getPassword());
        entity.setPassword(password);

        //保存用户
        entity.setSuperAdmin(SuperAdminEnum.NO.value());
        insert(entity);

        //保存角色用户关系
        sysRoleUserService.saveOrUpdate(entity.getId(), dto.getRoleIdList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysUserDTO dto) {

        this.verifyUsernameAndMobile(dto);

        SysUserEntity entity = ConvertUtils.sourceToTarget(dto, SysUserEntity.class);

        //密码加密
        if (StringUtils.isBlank(dto.getPassword())) {
            entity.setPassword(null);
        } else {
            String password = PasswordUtils.encode(entity.getPassword());
            entity.setPassword(password);
        }

        //更新用户
        updateById(entity);

        //更新角色用户关系
        sysRoleUserService.saveOrUpdate(entity.getId(), dto.getRoleIdList());
    }

    /**
     * 用户名与手机号查重
     *
     * @param dto 用户新增或修改时的提交数据
     * @return void
     * @author nanning
     */
    private void verifyUsernameAndMobile(SysUserDTO dto) {
        QueryWrapper<SysUserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(FieldConstant.DEL_FLAG, DelFlagEnum.NORMAL.value())
                .ne(null != dto.getId(), "id", dto.getId())
                .and(i -> i.eq(StringUtils.isNotBlank(dto.getMobile()), "mobile", dto.getMobile())
                        .or()
                        .eq("username", dto.getUsername()));
        Integer selectCount = this.baseDao.selectCount(wrapper);
        if (selectCount > NumConstant.ZERO) {
            throw new NNException("保存失败，用户名或手机号重复");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long[] ids) {
        //逻辑删除
        logicDelete(ids, SysUserEntity.class);

        //角色用户关系，需要保留，不然逻辑删除就变成物理删除了
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePassword(Long id, String newPassword) {
        newPassword = PasswordUtils.encode(newPassword);

        baseDao.updatePassword(id, newPassword);
    }

    @Override
    public int getCountByDeptId(Long deptId) {
        return baseDao.getCountByDeptId(deptId);
    }

    @Override
    public Result<GridLeaderRegisterDTO> listGridWhileLeaderRegister(String mobile) {

        QueryWrapper<SysUserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(FieldConstant.MOBILE, mobile)
                .eq(FieldConstant.DEL_FLAG, DelFlagEnum.NORMAL.value());

        Integer selectCount = baseDao.selectCount(wrapper);
        if (selectCount == NumConstant.ZERO) {
            return new Result().error("匹配网格长手机号失败");
        }

        SysUserEntity sysUserEntity = baseDao.selectOne(wrapper);
        SysUserDTO dto = ConvertUtils.sourceToTarget(sysUserEntity, SysUserDTO.class);

        List<String> gridIdList = this.baseDao.selectListLeaderGridId(mobile);
        if (CollUtil.isEmpty(gridIdList)) {
            return new Result().error("匹配网格长数据权限失败");
        }

        List<GridForLeaderRegisterDTO> gridForLeaderList = sysDeptService.selectListGridForLeader(gridIdList);

        GridLeaderRegisterDTO result = new GridLeaderRegisterDTO();
        result.setSysUser(dto);
        result.setLeaderGridList(gridForLeaderList);
        return new Result<GridLeaderRegisterDTO>().ok(result);
    }

    @Override
    public List<Long> listOfUserIdsByDeptId(Long deptId) {
        return baseDao.selectListOfUserIdsByDeptId(deptId);
    }

    @Override
    public Result modifyOpenIdByUsername(SysUserOpenIdFormDTO sysUserOpenIdFormDto) {
        // 查询当前openId是否绑定过账户
        SysUserDTO userDto = this.getSysUserInfoByOpenId(sysUserOpenIdFormDto.getOpenId());
        if (null != userDto) {
            // 解绑旧帐户
            SysUserEntity entity = new SysUserEntity();
            entity.setId(userDto.getId());
            entity.setOpenId("");
            baseDao.updateById(entity);
        }
        // 绑定新账户
        baseDao.updateOpenIdByUsername(sysUserOpenIdFormDto);

        return new Result();
    }

    @Override
    public SysUserDTO getSysUserInfoByOpenId(String openId) {
        return baseDao.selectOneOfSysUserByOpenId(openId);
    }

    @Override
    public void updateUserOpenId(Long userId) {
        baseDao.updateUserOpenId(userId);
    }

    @Override
    public Result<List<String>> getUserPhoneByListDeptId(List<Long> deptId) {
        Map<String,Object> map = new HashMap<>();
        map.put("deptId",deptId);
        List<String> list = baseDao.getUserPhoneByListDeptId(map);
        return new Result<List<String>>().ok(list);
    }

    @Override
    public Result<List<String>> getSysGridLeaderPhone(Long deptId) {
        return new Result<List<String>>().ok(baseDao.getSysGridLeaderPhone(deptId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String getUserInfoByGridAndMobile(EpdcScripUserInfoFormDTO epdcScripUserInfoFormDTO) {
        SysUserDTO userDTO = baseDao.selectOneUserInfoByGridAndMobile(epdcScripUserInfoFormDTO);
        if(userDTO==null){
            throw new NNException("您的手机号未绑定账号信息");
        }
        String randomValue = String.valueOf((int)(Math.random()*(1000000-100000)+100000));
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setScrip(randomValue);
        userEntity.setId(userDTO.getId());
        updateById(userEntity);
        return randomValue;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysUserDTO getByScrip(String scrip) {
        if(StringUtils.isBlank(scrip)){
            throw new NNException("临时凭证不能为空");
        }
        SysUserDTO sysUserDTO =  baseDao.selectOneUserInfoByScrip(scrip);
        if(sysUserDTO == null){
            throw  new NNException("根据临时凭证无法获取到用户");
        }
        //获取后清除临时凭证
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setScrip("");
        userEntity.setId(sysUserDTO.getId());
        updateById(userEntity);
        return sysUserDTO;
    }

    @Override
    public String getScripBySysUserId(Long id) {
        SysUserEntity sysUserEntity = baseDao.selectById(id);
        if(sysUserEntity==null){
            throw new NNException("未查询到相关账号信息");
        }
        String randomValue = String.valueOf((int)(Math.random()*(1000000-100000)+100000));
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setScrip(randomValue);
        userEntity.setId(sysUserEntity.getId());
        updateById(userEntity);
        return randomValue;
    }

}
